package design.mode.dispatcher.util.excel;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.write.builder.ExcelWriterSheetBuilder;
import com.alibaba.excel.write.merge.OnceAbsoluteMergeStrategy;
import design.mode.dispatcher.bean.DemoData;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.List;
import java.util.stream.Collectors;

/**
 * easyexcel根据列重复数据动态合并单元格
 */
public class ExcelUtil2 {
    public static void main(String[] args) {
        String fileName = "D:/" + "simpleWrite" + System.currentTimeMillis() + ".xlsx";
        System.out.println(fileName);
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        List<DemoData> data = Arrays.asList(
                new DemoData("string1", dateFormat.format(new Date()), 23.5),
                new DemoData("string3", dateFormat.format(new Date()), 23.4),
                new DemoData("string2", dateFormat.format(new Date()), 23.6),
                new DemoData("string2", dateFormat.format(new Date()), 23.7),
                new DemoData("string3", dateFormat.format(new Date()), 23.5),
                new DemoData("string3", dateFormat.format(new Date()), 23.5),
                new DemoData("string3", dateFormat.format(new Date()), 23.5),
                new DemoData("string2", dateFormat.format(new Date()), 23.5)
        );

        List<OnceAbsoluteMergeStrategy> mergeStrategyList = getMergeStrategy(data);
        List<OnceAbsoluteMergeStrategy> mergeStrategyList1 = getMergeStrategy1(data);


        ExcelWriterSheetBuilder excelWriterSheetBuilder = EasyExcel.write(fileName).head(DemoData.class)
                .sheet("模版");
//       逐个添加合并策略
        for (OnceAbsoluteMergeStrategy strategy : mergeStrategyList) {
            excelWriterSheetBuilder = excelWriterSheetBuilder.registerWriteHandler(strategy);
        }
        excelWriterSheetBuilder.doWrite(data);
        for (OnceAbsoluteMergeStrategy strategy : mergeStrategyList1) {
            excelWriterSheetBuilder = excelWriterSheetBuilder.registerWriteHandler(strategy);
        }
//        导出数据
        excelWriterSheetBuilder.doWrite(data);
    }

    public static List<OnceAbsoluteMergeStrategy> getMergeStrategy(List<DemoData> list) {
//      合并开始行
        int startRowIndex = 0;
//      合并结束行
        int endRowIndex = 0;
//      合并开始列
        int colStartIndex = 0;
//      合并结束列
        int colEndIndex = 0;
        List<OnceAbsoluteMergeStrategy> strategyList = new ArrayList<>();
//       取出string列的数据
        List<String> stringList = list.stream().map(DemoData::getString).collect(Collectors.toList());

//       前后添加两个不计入合并的元素 , 类似链表中哨兵，简化索引越界的判断
        stringList.add(0, "开始节点不计入合并");
        stringList.add(stringList.size(), "结束节点不计入合并");


        for (int index = 1; index < stringList.size() - 1; index++) {
            // 当前的元素和数组中前一个元素是否相等
            boolean equalsPrevious = Objects.equals(stringList.get(index), stringList.get(index - 1));
            // 当前的元素和数组中后一个元素是否相等
            boolean equalsAfter = Objects.equals(stringList.get(index), stringList.get(index + 1));
//            如果找到一个元素和不等于前面，但是等于后面，则这个元素的索引就是一个OnceAbsoluteMergeStrategy的开始行
            if (!equalsPrevious && equalsAfter) {
                startRowIndex = index;
                //            如果找到一个元素和等于前面，但是不等于后面，则这个元素的索引就是一个OnceAbsoluteMergeStrategy的结束结束行
            } else if (equalsPrevious && !equalsAfter) {
                endRowIndex = index;
//              创建单个合并策略，并添加到策略列表里面去
                OnceAbsoluteMergeStrategy strategy = new OnceAbsoluteMergeStrategy(startRowIndex, endRowIndex, colStartIndex, colEndIndex);
                strategyList.add(strategy);
            }

        }

        return strategyList;
    }
    public static List<OnceAbsoluteMergeStrategy> getMergeStrategy1(List<DemoData> list) {
//      合并开始行
        int startRowIndex = 0;
//      合并结束行
        int endRowIndex = 0;
//      合并开始列
        int colStartIndex = 0;
//      合并结束列
        int colEndIndex = 0;
        List<OnceAbsoluteMergeStrategy> strategyList = new ArrayList<>();
//       取出string列的数据
        List<Double> collect = list.stream().map(DemoData::getDoubleData).collect(Collectors.toList());

//       前后添加两个不计入合并的元素 , 类似链表中哨兵，简化索引越界的判断
        collect.add(0, 0.00);
        collect.add(collect.size(), 1.00);


        for (int index = 1; index < collect.size() - 1; index++) {
            // 当前的元素和数组中前一个元素是否相等
            boolean equalsPrevious = Objects.equals(collect.get(index), collect.get(index - 1));
            // 当前的元素和数组中后一个元素是否相等
            boolean equalsAfter = Objects.equals(collect.get(index), collect.get(index + 1));
//            如果找到一个元素和不等于前面，但是等于后面，则这个元素的索引就是一个OnceAbsoluteMergeStrategy的开始行
            if (!equalsPrevious && equalsAfter) {
                startRowIndex = index;
                //            如果找到一个元素和等于前面，但是不等于后面，则这个元素的索引就是一个OnceAbsoluteMergeStrategy的结束结束行
            } else if (equalsPrevious && !equalsAfter) {
                endRowIndex = index;
//              创建单个合并策略，并添加到策略列表里面去
                OnceAbsoluteMergeStrategy strategy = new OnceAbsoluteMergeStrategy(startRowIndex, endRowIndex, colStartIndex, colEndIndex);
                strategyList.add(strategy);
            }

        }

        return strategyList;
    }

}
